Merge Agentspan SDK and Implement following the Implementation Guide#131
Open
kowser-orkes wants to merge 19 commits into
Open
Merge Agentspan SDK and Implement following the Implementation Guide#131kowser-orkes wants to merge 19 commits into
kowser-orkes wants to merge 19 commits into
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests.
Flags with carried forward coverage won't be shown. Click here to find out more. 🚀 New features to boost your workflow:
|
kowser-orkes
pushed a commit
that referenced
this pull request
Jul 9, 2026
actions/setup-python's `cache: pip` hard-fails when the repo has no requirements.txt or pyproject.toml to hash for the cache key — true for this repo, where Python exists only to run mcp-testkit. Carried over from the Python SDK's agent-e2e workflow, where a pyproject.toml exists. First observed on PR #131: the job died in "Set up Python" before any test ran, and the silently-empty guard correctly reported 0/0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
df8aa64 to
d43dea6
Compare
…orts Merge the Agentspan TypeScript SDK source (@conductor-oss/conductor-agent-sdk 0.3.0, agentspan@f8704fa3) into this package as src/agents/, published only via subpath exports: ./agents, ./agents/testing, ./agents/vercel-ai, ./agents/langgraph, ./agents/langchain. The root export surface is byte-identical to before (verified via compiler API), so the one name collision (Action) never materializes. Changes beyond the verbatim copy: - agent-client.ts / worker.ts: import from ../sdk and ../open-api instead of the package name (the only coupling to the workflow layer) - tool.ts: rename the createRequire binding to peerRequire (top-level `require` is reserved in this repo's CJS module flavor) - lint conformance to this repo's strict+stylistic ruleset (~41 fixes: no-op arrows, guard-throws replacing non-null assertions, Reflect.deleteProperty, for-of); no-explicit-any and no-unsafe-function-type stay at upstream's own "warn" contract via a scoped eslint override - tsup.config.ts replaces the inline package.json block: 6 entries, esm+cjs+dts; optional peers external; verify:dist gate loads every exports subpath in both formats - package.json: dotenv to dependencies (import-time side effect in config.ts), 5 optional peerDependencies, sideEffects allowlists dist/agents/**, tsx/zod/zod-to-json-schema devDeps - tsconfig: lib es2022 -> es2023 (stream.ts uses Array.findLast; superset, Node >= 18 supports it), package-name paths for in-repo resolution Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
38 of upstream's 41 unit/cli-bin suites move to src/agents/__tests__/, where
the existing test:unit glob and per-PR CI matrix pick them up with zero
workflow changes. Test-count parity with upstream vitest is exact:
761 = 860 - 99 in the three deferred files. Deferred:
- kitchen-sink-structural.test.ts (imports examples/kitchen-sink; lands with
the examples in the next commit)
- validation/{algorithmic,event-audit}.test.ts (they test the validation/
LLM-judge harness, whose migration is explicitly deferred)
Port mechanics: vitest imports -> @jest/globals, vi.* -> jest.*,
toBeTypeOf/toHaveBeenCalledOnce -> jest equivalents, vi.stubGlobal -> local
helpers/stub-global.ts (upstream never unstubs; per-file isolation contains
it), relative ../../src paths -> colocated paths, skills fixtures colocated
under __tests__/fixtures/. The two jest.mock("child_process") factories
hoist correctly under ts-jest (verified green).
cli-bin/ lands at repo root (the Go CLI walk-up probe expects <dir>/cli-bin)
with imports retargeted to src/agents/. deploy.ts gets a type-only fix for
its workflowName read (upstream never typechecked cli-bin; runtime shape
unchanged).
jest.config.mjs: package-name mappers to in-repo sources plus the standard
ESM .js-suffix strip for relative imports. eslint: upstream's warn contract
extended to cli-bin; stylistic-only relaxations scoped to the migrated tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
221 example files (top-level + quickstart + adk/langgraph/openai/vercel-ai framework subdirs) land at examples/agents/, the 6 agent docs at docs/agents/ (sidestepping the README and api-reference path collisions). All imports and install instructions rewritten from @conductor-oss/conductor-agent-sdk to @io-orkes/conductor-javascript (/agents subpaths), including the runtime error-message strings in src/agents wrappers — zero old-name references remain outside git history. Run story: top-level/quickstart examples resolve the package name straight to src/agents via examples/agents/tsconfig.json paths (npx tsx, no install); framework subdirs install their own deps (scripts/install-example-deps.sh, nonexistent langchain/ entry dropped) and gain an explicit file:../../.. SDK dep; langgraph/ also gains the @langchain deps it silently inherited from upstream's deleted examples workspace manifest. Also lands the deferred kitchen-sink-structural.test.ts (66 tests; unit suite now 1500 green) and a type-only fix upstream never caught because examples were never typechecked: schedules-api.ts runNow's first overload makes opts optional, matching the documented 1-arg default usage. Root tsconfig excludes examples/agents (framework subdir deps are not installed at the root); eslint gains a scoped override for the four rules the didactic files break en masse — upstream ignored examples/ in lint entirely. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
All 25 upstream e2e suites move to e2e/ (with fixtures/, _configs/, and the
loose harness scripts under e2e/tools/), run by jest.e2e.config.mjs:
testMatch e2e/**, 60s default timeout, maxWorkers 3 (upstream's maxForks 3),
jest-junit to results/junit-e2e.xml. New script: npm run test:agent-e2e
(--forceExit, matching the repo's other jest scripts — agent polling keeps
handles open after LLM suites). Deliberately invisible to
test/test:unit/test:integration globs — per-PR CI cost is unchanged
(verified: unit run still 74 suites).
Beyond the mechanical vitest-to-jest pass, six vitest-isms needed real
porting (verified by loading all 25 suites under jest — 196 tests enumerate
clean — and by running suites 1/2/9 against a live release-JAR server):
- expect(actual, message) two-arg form (265 sites, jest 30 rejects it) ->
expectMsg helper in e2e/helpers.ts that prepends the diagnostic message
to matcher failures
- describe(name, { timeout }, fn) options object (19 files) -> file-level
jest.setTimeout
- it.skipIf(cond) (19 sites) -> itSkipIf helper
- it.fails -> it.failing (suite 7)
- it(name, { retry: 2 }, fn) (4 sites) -> file-level jest.retryTimes(2)
(jest has no per-test retry; both files are LLM-variability suites)
- top-level await gates (suites 11/21/23; illegal in CJS) -> synchronous
require for the langgraph availability probe, and fail-hard beforeAll
health/scheduler gates (matches the TS-e2e fail-hard philosophy; the CI
workflow health-gates the server before tests run)
Live-server proof (local V1): suites 1/2/9 against agentspan-server 0.4.0 —
11 tests pass; the only failures are server-side OpenAI 401s from the
missing local LLM key (the CI run with repo secrets is the full proof).
Unused-var noise (port artifacts + upstream) fixed with _-prefixes and
import trims; the stylistic eslint relaxations for migrated tests extend to
e2e/**. jest-junit output dirs (reports/, results/) are now gitignored.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Port of the Python SDK's implemented agent-e2e workflow. Kept verbatim: pull_request + workflow_dispatch triggers, per-ref concurrency with cancel-in-progress, pinned AGENTSPAN_VERSION 0.4.0 (server JAR from the GitHub release, cached by version; linux CLI binary), temurin 21, hard 90s health gate that dumps server.log on failure, executed>0 junit guard (defense-in-depth here — the TS suites fail hard when the server is down), junit + HTML + server.log artifacts at 14-day retention, 45-min timeout, job-level OPENAI_API_KEY/ANTHROPIC_API_KEY secrets (must be added to this repo's settings before the first live run). JS deltas: Node 22 + npm ci + npm run build + npm run test:agent-e2e as the test step; Python setup retained only for mcp-testkit; HTML report via npx tsx e2e/generate-report.ts; no CONDUCTOR_MP_START_METHOD (Python multiprocessing concern, no JS analog). Rehearsed locally: actionlint clean; health gate passed against the booted 0.4.0 JAR; guard correctly fails an all-skipped junit (0/196) and the report generator renders the real junit output. The test:agent-e2e script pins jest-junit's output to results/junit-e2e.xml via env vars — the package.json jest-junit block (reports/jest-junit.xml) outranks reporter options, and env vars outrank the block. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
README: new Durable AI Agents section (subpath quickstart mirroring examples/agents/quickstart/01-basic-agent.ts, wrapper/testing subpaths, docs + examples pointers) and a Documentation-table row. AGENTS.md: src/agents feature area — repo layout additions (src/agents, e2e/, cli-bin/, examples/agents, docs/agents), the subpath-only export rule (root re-export ban and the OpenAPI Action collision that motivates it), colocated-test and e2e conventions, example run story, AGENTSPAN_* config surface, and the agent-e2e command. CHANGELOG: additive-minor entry with a migration note for @conductor-oss/conductor-agent-sdk users (specifier rewrite, /agents-prefixed wrapper subpaths, optional peers, dotenv/sideEffects behavior). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
actions/setup-python's `cache: pip` hard-fails when the repo has no requirements.txt or pyproject.toml to hash for the cache key — true for this repo, where Python exists only to run mcp-testkit. Carried over from the Python SDK's agent-e2e workflow, where a pyproject.toml exists. First observed on PR #131: the job died in "Set up Python" before any test ran, and the silently-empty guard correctly reported 0/0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The Stage-4 lint pass blanket-prefixed suite 10's diag and codeOutputs locals as unused, but most scopes still reference the bare names inside expectMsg messages and output assertions — ReferenceError at runtime. ts-jest is transpile-only, so it surfaced only in the first secrets- enabled CI run (6 failures, the run's only red). Only genuinely-unused declarations keep the underscore (upstream parity; upstream never linted e2e). Verified live: suite 10 vs local server JAR 0.4.0 with real keys — 8 passed, 1 skipped (Jupyter, needs kernel). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4141a1e to
6c75d48
Compare
… agent lifecycle surface Per-schedule pause/resume verbs differ by server family: OSS/embedded Conductor maps them PUT-only, Orkes Conductor GET-only. SchedulerClient now issues PUT first and retries via GET only on HTTP 405, stateless per call, with the pause reason re-applied on the fallback URL (mirrors the Python SDK's OrkesSchedulerClient). Implemented in the hand-written wrapper via raw non-throwing client calls — the generated transport is untouched and regeneration stays safe. SchedulerClient also absorbs the typed agent-schedule lifecycle surface (save/get/listForAgent/pause/resume/delete/runNow/previewNext/reconcile) operating on Schedule/ScheduleInfo with wire-name prefixing and typed errors via _translate. The models/mapping/errors relocate verbatim from src/agents/schedule.ts to src/sdk/clients/agent/schedule.ts (Python parity: conductor/client/ai/schedule.py); the agents module re-exports them. Ctor widened to Client | PromiseLike<Client> so callers with async client construction keep synchronous accessors. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…e SchedulerClient
BREAKING CHANGE (agent layer, no backward compatibility): the raw-fetch
ScheduleClient class and SchedulerFetcher interface are gone from the
./agents surface. SchedulerClient — which absorbed the same typed
lifecycle methods (save/get/listForAgent/pause/resume/delete/runNow/
previewNext/reconcile) in the previous commit — is re-exported from
./agents in their place; every method call site keeps its name and
signature. The scheduling e2e suite needed exactly two lines (import +
one type annotation); the schedules.* module facade, runtime
schedulesClient(), deploy({schedules}) reconciliation and
AgentClient.schedule() are unchanged.
AgentClient.schedules now hands its memoized Conductor-client promise to
SchedulerClient (single transport; the SchedulerFetcher raw-fetch path is
deleted, _rawRequestUntyped remains for /agent/* control-plane calls).
An absence test pins the deletion, mirroring the Python SDK's
test_agent_schedule_client_is_gone.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…posed via OrkesClients
Moves the agent control-plane client and the agent-flavored workflow
client from src/agents/ to src/sdk/clients/agent/ (names kept — nothing
on the root surface collides: Conductor's workflow client is
WorkflowExecutor). OrkesClients gains getAgentClient() and
getAgentWorkflowClient(); AgentClient's constructor accepts an optional
pre-built client ((AgentConfigOptions & {client?}) | AgentConfig) which
pre-seeds the memoized promise, so the factory path reuses one Conductor
client across workflow + schedule surfaces. The /agent/* raw transport
and JWT mint path are unchanged; decodeJwtExp stays exported.
Cycle guard: the moved files import createConductorClient and the agent
domain modules via deep paths, never the sdk barrel; madge reports no
new cycles (the AgentClient↔WorkflowClient type-only edge predates the
move). The ./agents subpath re-exports everything from the new homes —
its surface is unchanged. The enriched ConductorClient type is not
re-exported at root (the deprecated bare alias keeps that name).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CHANGELOG (Unreleased): OrkesClients agent getters, PUT-first/405→GET pause-resume verb handling, absorbed typed schedule lifecycle, and the ScheduleClient/SchedulerFetcher removal with its one-line migration. Agent docs re-point the schedule surface at SchedulerClient and note the WorkflowExecutor vs agent WorkflowClient distinction. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d client's request pipeline; SSE auth borrowing (spec R1/R2) Fork point: feature/combine-agentspan @ a410bad. Executes idea-12/design-typescript.md DD2-DD4 (analysis-typescript.md T1/T6/T7/T10/T13). - handleAuth gains getToken() (TTL-aware, reuses the existing guarded refresh); createConductorClient exposes getAuthenticationHeaders()/stopBackgroundRefresh() on the returned client so /agent/* can borrow the shared client's token instead of minting a second one (R2). - Split AgentClient into an interface (11 spec ops: startAgent, deployAgent, compile, status, getExecution, listExecutions, respond, stop, signal, stream, close) and a new OrkesAgentClient implementation. Every non-streaming call rides client.request(...) with one error choke point (404 -> AgentNotFoundError, else -> AgentAPIError), killing the raw-fetch transport and the T10 plain-Error leak. Deleted _token/_tokenExp/_mintPromise/_authHeaders/_mintToken/decodeJwtExp and the raw _request/_rawRequestUntyped methods. An explicit config.apiKey (already-minted token) still wins verbatim, wired onto both the SSE header provider and the shared client's own auth so REST calls carry it too. - AgentStream takes a header provider (() => Promise<Record<string,string>>) resolved fresh per (re)connect instead of a static snapshot (T7); accepts an initial lastEventId; gained close() and a dedicated SSEUnavailableError for non-2xx initial-connect rejection (falls straight to the polling fallback). - OrkesClients.getAgentClient() returns the AgentClient interface type; AgentRuntime.client is now an OrkesAgentClient built on the same transport. - Rewrote the tests that pinned the old internals: agent-client-auth.test.ts (now the R2 spec guard: one mint across N /agent/* calls, anonymous path sends no header), the runtime.test.ts _httpRequest/SSE/stream/credentials suites (mock the generated OpenAPI transport instead of global.fetch directly), OrkesClients.agent.test.ts and suite23 (ctor rename). Not yet done (S2+): AgentConfig slimming, worker-plane transport reroute, CONDUCTOR_*->AGENTSPAN_* env fallback, RunSettings, runtimeMetadata credentials, liveness, swarm transfer contract. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…gentConfig; one client for control+worker planes; CONDUCTOR_*->AGENTSPAN_* env chain (spec R3/R4/R5) Executes idea-12/design-typescript.md DD5-DD7 (analysis-typescript.md T3/T4/T11). - AgentRuntime ctor becomes (configuration?: OrkesApiConfig | ConductorClient, settings?: AgentConfigOptions) - connection/auth split from behavior knobs, no shim (agent layer unreleased; all 232 example constructions are zero-arg). Builds ONE shared ConductorClient (or adopts an injected one), wraps it in OrkesAgentClient. runtime.client narrows to the AgentClient interface (spec R1 surface); a private _agentClient reference carries the full surface (workflows/schedules/request escape-hatch) for the runtime's internal use. - OrkesAgentClient's own ctor slims to (configuration?: OrkesApiConfig | ConductorClient) - no more embedded AgentConfig/apiKey passthrough (moved fully to the shared client's keyId/keySecret model). Exposes apiBaseUrl()/apiBaseUrlSync() so callers building SSE URLs don't need config.serverUrl (which no longer exists). - AgentConfig slimmed to 7 behavior-only knobs: workerPollIntervalMs, workerThreadCount (renamed from workerThreads, now wired to ConductorWorker.concurrency instead of a hardcoded 1), autoStartWorkers (gates startPolling() in run/start; serve always starts), streamingEnabled (wired via AgentStream's new skipSse flag -> straight to the polling fallback), livenessEnabled/livenessStallSeconds/livenessCheckIntervalSeconds (config lands now; S5 adds the reader). Deleted: serverUrl, apiKey, authKey, authSecret, logLevel, llmRetryCount, credentialStrictMode, autoStartServer, daemonWorkers, normalizeServerUrl. - WorkerManager takes a getClient() resolver instead of building its own client: deleted the header-injecting custom fetch, the headersProvider plumbing, and the process.env.CONDUCTOR_SERVER_URL clobber (T4). Retains serverUrl/headers fields (now derived from the shared client) only for the pre-S4 resolveCredentials()/runWithCredentialContext() pull path. - resolveOrkesConfig gains the R3 env chain: host CONDUCTOR_SERVER_URL -> explicit config -> AGENTSPAN_SERVER_URL -> localhost:8080 default; auth CONDUCTOR_AUTH_KEY/SECRET -> explicit -> AGENTSPAN_AUTH_KEY/SECRET. The unconditional console.warn for missing CONDUCTOR_AUTH_KEY/SECRET now routes through the configured (or default) logger at debug. DefaultLogger's default level gains the same env chain (CONDUCTOR_LOG_LEVEL -> AGENTSPAN_LOG_LEVEL -> INFO). - Rewrote the tests that pinned the deleted fields or the old transport: config.test.ts (7-knob set + a type-level guard that AgentConfigOptions carries no connection/auth/log keys), worker.test.ts (shared-client getClient() resolver + concurrency wiring), runtime.test.ts (ctor split + keyId/keySecret in place of apiKey/authKey), resolveOrkesConfig.test.ts + createConductorClient.test.ts (new fallback/default coverage), OrkesClients.agent.test.ts and suite23 (cast to OrkesAgentClient where the narrow interface no longer exposes workflows/schedules/getClient). Not yet done (S3+): verb contract (serve=deploy+serve, variadic deploy, handle stop), RunSettings, runtimeMetadata credentials, liveness reader, swarm transfer contract. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…y; handle stop; RunSettings per-run overrides (spec R8/R9)
- serve(...agents, {blocking?}) deploys each agent (native + framework) before
registering/starting its workers; blocking:false returns after deploy +
registration + polling start instead of waiting for SIGINT/SIGTERM.
Trailing-arg detection reuses detectFramework + a keys-subset check so a
real Agent/framework object is never misclassified as options.
- deploy() gains a variadic overload (deploy(...agents) -> DeploymentInfo[])
alongside the existing deploy(agent, opts?) form; both share a new
_deployViaServer helper (also used by serve).
- AgentHandle (native + framework) gains stop(): client.stop() + best-effort
client.signal(id, "stopped") to unblock any pending wait(), mirroring
ClientHandle's existing routing.
- New RunSettings type (model/temperature/maxTokens/reasoningEffort/
thinkingBudgetTokens) applied to the serialized agentConfig immediately
before startAgent in run()/start() (stream() delegates to start());
null-check gating so zero values (temperature: 0) still apply; unknown
keys throw. RunOptions.model becomes sugar for runSettings.model on all
paths (native + framework); an explicit runSettings.model wins.
Fork point a410bad on feature/combine-agentspan; design DD9/DD10
(idea-12/design-typescript.md).
v1r3n
reviewed
Jul 14, 2026
| } | ||
|
|
||
| /** Same security metadata the generated `SchedulerResource` methods declare. */ | ||
| const X_AUTHORIZATION_SECURITY = [ |
added 3 commits
July 13, 2026 19:31
…ed; retire /workers/secrets; agent-e2e two-server matrix (spec R6/R12) - Dispatch (worker.ts _wrapWorker): replace execution-token extraction + resolveCredentials POST with a read of the polled task's runtimeMetadata (typed local extension, no OpenAPI regen). Any declared credential name missing from the delivered map -> NonRetryableException naming the missing names and the required server capability. Ambient process.env is never read as a fallback. injectSecretsForInvocation's mutex-protected env injection is unchanged -- only the source of resolved values changed. - Deletions (R12): resolveCredentials, extractExecutionToken, all __agentspan_ctx__/executionToken handling, /workers/secrets references. CredentialContext now holds resolved name->value pairs directly; getCredential()/runWithCredentialContext()/setCredentialContext() keep their conceptual role but take the delivered map, not a token to resolve. WorkerManager's now-dead _serverUrl/headers fields (kept from S2 for the pull path) are removed. - e2e/helpers.ts gains two session-scoped capability probes: checkRuntimeMetadataCapability() (register/read-back a scratch TaskDef) and checkSecretWriteCapability() (probe PUT /secrets) -- both needed because a standalone conductor-oss server's secret store is env-backed and read-only. Wired into test_suite2 (full skip) and test_suite4/5 (Phase 2 skip) so credential-lifecycle assertions degrade gracefully instead of failing hard on an incapable server. - .github/workflows/agent-e2e.yml: matrix over server flavor (fail-fast off) -- Lane A (agentspan, bumped 0.4.0 -> 0.4.4) kept verbatim; Lane B (conductor-oss v3.32.0-rc.8, boot jar from Maven Central -- no GitHub release assets) added, verified locally (health shape, /api/agent/* plane, runtimeMetadata round-trip, and a real LLM-only run all confirmed live against the downloaded jar). No LLM-integration registration step needed -- both servers read OPENAI_API_KEY/ANTHROPIC_API_KEY directly from the server process's own environment. Deviation from the plan's file list (necessary consequence of the R12 deletion, not scope creep): examples/16h-credentials-external-worker.ts imported the two deleted functions directly and is rewritten to read runtimeMetadata off the polled task instead; examples/16-credentials- isolated-tool.ts and serializer.ts had comments describing the retired execution-token mechanism, now corrected. test_suite1's plan-compile test had the same stale comment, also fixed. Fork point a410bad on feature/combine-agentspan; design DD8 (idea-12/design-typescript.md).
…rm transfer hand-off contract (spec R11/R13)
R11 — liveness: new src/agents/liveness.ts LivenessMonitor polls the workflow
every livenessCheckIntervalSeconds (config knobs already landed in S2) for a
stateful (domain-routed) run; a SCHEDULED/IN_PROGRESS task in that domain with
pollCount=0 for longer than livenessStallSeconds fires a new WorkerStallError
(errors.ts), rejecting a blocking wait() instead of hanging forever. Only
wired for native start() — framework agents never route through a domain, so
there's nothing to watch. Monitor self-stops on terminal workflow status or
handle disposal (wait()/stop()).
wait() deadline (T9 sibling): both the native and framework handle's wait()
now cap at timeoutSeconds*1000+30s (or a 600s default), throwing AgentAPIError
naming the last status — mirrors OrkesAgentClient's existing ClientHandle.wait.
R13 — swarm transfer contract: the per-tool transfer no-op worker now accepts
an optional `message` and echoes {message} back when non-empty ({} otherwise,
backward compatible). The {agent}_check_transfer worker adds `transfer_message`
(the winning call's inputParameters.message, tolerating an older `arguments`
key variant, stringified, "" when absent) and `dropped_transfers` for
non-winning transfer calls when there is more than one, with a warning naming
the honored and dropped targets — a fan-out intent is never silently dropped.
Tests: new liveness.test.ts unit-tests LivenessMonitor directly (domain
gating, dedup, terminal auto-stop, error-swallowing) with fake timers;
runtime.test.ts adds wiring tests (stateful-only, livenessEnabled:false,
end-to-end stall -> WorkerStallError, deadline expiry) plus a local
afterEach(jest.restoreAllMocks()) since LivenessMonitor.prototype spies (unlike
this file's per-instance spies) leak across tests without it; swarm-workers.test.ts
extends check_transfer/transfer-worker coverage for the new output shape.
Validation: tsc shows only the pre-existing Mock<UnknownFunction> test-mock
typing pattern growing by the same handful of new call sites (no new category);
lint 0 errors; full unit suite 1566/1566; build clean (6 dist entrypoints).
…credential + liveness docs
CHANGELOG.md [Unreleased] rewritten to the final agent-layer shape (no
migration-shim framing -- the layer is still unreleased): AgentClient
interface via OrkesClients.getAgentClient()/runtime.client sharing one
Conductor client; AgentRuntime(configuration, settings) ctor; behavior-only
AgentConfig; verb contract (serve = deploy + serve, blocking, variadic
deploy, handle stop, deadline-aware wait()); RunSettings; runtimeMetadata
credentials (fail-closed, server-capability note); liveness monitoring;
swarm hand-off contract. Released-surface additive lines called out
separately: resolveOrkesConfig's AGENTSPAN_* fallback + localhost:8080
default, getAuthenticationHeaders/stopBackgroundRefresh, logger env chain.
docs/agents/{api-reference,advanced,writing-agents}.md: corrected drift
accumulated across Stages 1-5 (AgentClient was documented as a directly
instantiable class; AgentConfigOptions still listed deleted connection/dead
fields; credentials described as pulled from a secret store rather than
delivered wire-only on Task.runtimeMetadata). Added RunSettings and
liveness monitoring sections (previously undocumented), WorkerStallError,
and the R10 "no per-run mutable capture" invariant for tool() authors.
examples/agents/: 63-deploy.ts/63b-serve.ts/63c-run-by-name.ts headers
rewritten for the serve-deploys contract (serve() no longer requires a
prior deploy() call). Scripted, comment-only sweep across 100 example
files' "Production pattern" footer wording to match (zero code churn,
verified via git diff --stat).
Validation: lint 0 errors (358 pre-existing warnings), tsc baseline-clean
(285, unchanged), build clean, unit 1566/1566.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
1. Merge the Agentspan agent SDK into conductor-javascript
Folds the Agentspan TypeScript SDK (
@conductor-oss/conductor-agent-sdk) into thispackage as a durable AI-agent layer, exposed only via new subpath exports — one install,
one package:
./agentsAgent,AgentRuntime,tool, guardrails, handoffs, multi-agent strategies./agents/testing./agents/vercel-ai,./agents/langgraph,./agents/langchainThe root export surface is unchanged — existing users are unaffected. Agent-layer deps
(
zod,ai,@langchain/*) are optional peers. Includessrc/agents/(verbatim fromupstream except an import seam, lint conformance, package rebrand), unit tests ported
vitest → jest, e2e suites,
examples/agents/,docs/agents/, a per-PRagent-e2eCIworkflow (boots the Agentspan server JAR + mcp-testkit against real LLMs), and a
verify:distbuild gate.2. Agent SDK guide-conformance follow-up (spec R1-R13)
Closes the gaps between the merged Agentspan agent layer and
AGENT_SDK_PORTING_SPEC.md— the same client surface, verb contract, credentialdelivery, and liveness/swarm behavior now match the spec and their Java/Python/C#
counterparts.
AgentClientis now an interface;OrkesAgentClientimplements it on the sharedclient's request pipeline — one
ConductorClient, one token mint, for both controland worker planes (spec R1/R2)
AgentRuntime(configuration?, settings?)— two independent optional args: connection(
OrkesApiConfig/ prebuilt client,CONDUCTOR_*→AGENTSPAN_*→localhost:8080fallback chain) vs. behavior (
AgentConfigOptions: polling, streaming, liveness).AgentConfigcarries only behavior now (R3/R4/R5)serve(...agents, { blocking? })deploys and serves in one call;deploygained a variadic form;
AgentHandle/ClientHandlegainedstop();wait()nowrejects on a deadline instead of hanging forever (R8/R9)
RunSettings(RunOptions.runSettings): per-runmodel/temperature/maxTokens/reasoningEffort/thinkingBudgetTokensoverrides, no cascade to sub-agents (R8)Task.runtimeMetadataat poll time, fail-closed (noambient-env fallback);
/workers/secretspull-token path retired (R6/R12)livenessStallSecondsrejects a blockingwait()withWorkerStallError; frameworkagents are unaffected (R11)
message;check_transferaddstransfer_message+dropped_transferswhen a turn emits more than one transfer (R13)agent-e2eCI matrix now runs against two server families:agentspan-serverand themainline
conductor-ossboot jardocs/agents/{api-reference,advanced,writing-agents}.md) and 100 examplesupdated to match;
CHANGELOG.mdrewritten for the final released surface🤖 Generated with Claude Code